<?php
/**
 * Created by PhpStorm.
 * User: 1
 * Date: 2017-07-10
 * Time: 15:04
 */

namespace app\index\command;


use app\index\helper\CommandHelper;
use app\src\base\helper\ValidateHelper;
use app\src\sunsun\common\action\PushLogAction;
use app\src\sunsun\common\action\TcpLogAction;
use app\src\sunsun\common\logic\UserDeviceLogic;
use app\src\sunsun\water_pump\action\WaterPumpDeviceEventAction;
use app\src\sunsun\water_pump\action\WaterPumpTcpLogAction;
use app\src\sunsun\water_pump\logic\WaterPumpDeviceEventLogic;
use app\src\sunsun\water_pump\logic\WaterPumpDeviceLogic;
use app\src\sunsun\water_pump\model\WaterPumpDeviceEvent;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;

class WaterPumpCommand extends Command
{
    protected function initialize(Input $input, Output $output)
    {
        CommandHelper::loadLang(['zh-cn', 'en', 'zh-tw']);
    }

    protected function configure()
    {
        $this->setName('device:water_pump')
            ->addOption('interval','',Option::VALUE_OPTIONAL,'device event process sleep {interval} seconds',30)
            ->addOption('size','',Option::VALUE_OPTIONAL,'device event process sizes per time',10)
            ->addOption('type','',Option::VALUE_OPTIONAL,'command type','clear')
            ->setDescription('water_pump device event process');
    }

    protected function execute(Input $input, Output $output)
    {
        $size = $input->getOption('size');
        $type = $input->getOption('type');
        $interval = $input->getOption('interval');
        $output->info('type= '.$type);

        switch (strtolower($type)){
            case 'process_event':
                $this->process_event($output,$size,$interval);
                break;
            case 'offline':
                $this->offline($output,$size);
                break;
            case 'clear':
                $this->clear($output);
                break;
            default:
                $this->clear($output);
                break;
        }
    }


    private function process_event(Output $output,$size=30,$interval=30){
        $output->info('process_event start');
        while (true){
            sleep($interval);
            $page = ['curpage'=>0,'size'=>$size];
            $userDeviceLogic = new UserDeviceLogic();
            $deviceEventLogic = new WaterPumpDeviceEventLogic();
            // 1. 查询所有未处理的变频水泵设备事件 分页，按时间从旧到新
            $result = $deviceEventLogic->query(['pro_status'=>WaterPumpDeviceEvent::PRO_STATUS_NOT_PROCESS],$page,"id asc");
            if(!$result['status']){
                $output->error($result['info']);
            }
            $list = $result['info']['list'];
            $now = time();
            $output->info('process count = '.count($list));
            $allEntity = [];
            foreach ($list as $item){
                // 2. 遍历所有事件
                $id  = $item['id'];
                $did = $item['did'];
                $eventType = $item['event_type'];
                $entity = ['update_time'=>$now,'pro_status'=>WaterPumpDeviceEvent::PRO_STATUS_PROCESSED];
                $entity['id'] = $id;

                $content = json_decode($item['event_info'],JSON_OBJECT_AS_ARRAY);
                if($eventType == 0 || $eventType == 1){
                    //无操作 实时信息
                    array_push($allEntity,$entity);
                    continue;
                }

                //最多取50个，一台设备被50个人以上绑定的情况不处理，效率
                $result = $userDeviceLogic->query(['did'=>$did],['curpage'=>0,'size'=>50]);

                if(ValidateHelper::legalArrayResult($result) && array_key_exists('list',$result['info'])){
                    $list = $result['info']['list'];
                    // 获取该设备的控制密码
                    $ctrl_pwd = CommandHelper::getCtrlPwd($did,new WaterPumpDeviceLogic());
                    $this->pushEventToUser($output,$ctrl_pwd,$list,$item);
                }
                array_push($allEntity,$entity);
            }
            if(count($allEntity) > 0){
                $result = (new WaterPumpDeviceEventLogic())->saveAll($allEntity);
                if($result['status']){
                    $output->info(' save_all = '.count($result['info']));
                }else{
                    $output->info(' save_all error = '.$result['info']);
                }
            }

        }
        $output->info('process_event end');
    }


    protected function pushEventToUser(Output $output,$ctrl_pwd,$list,$item){
        $time   = $item['create_time'];
        $did = $item['did'];
        $eventType = $item['event_type'];
        $output->info('wait pushing count = '.count($list));
        foreach ($list as $deviceItem) {
            $uid = $deviceItem['uid'];
            $timezone = intval($deviceItem['timezone']);
            $lang = $deviceItem['lang'];
            $extra = json_decode($deviceItem['extra'], JSON_OBJECT_AS_ARRAY);
            if (!is_array($extra) || !array_key_exists("pwd", $extra) || ($extra['pwd'] != 'sunsun123456' && $extra['pwd'] != $ctrl_pwd)) {
                $output->info('did=' . $did . ' password illegal uid=' . $uid);
                // 密码不一致就不需要处理
                continue;
            }

            if(is_array($extra) && array_key_exists('push_cfg',$extra)){
                $push_cfg = intval($extra['push_cfg']);
                if(intval($push_cfg) == 0){
                    // 推送开关关闭了，就无需推送
                    continue;
                }
            }

            $content = lang('water_pump_event_type_' . $eventType, '', $lang);
            $localTime = gmdate('H:i:s', $timezone * 3600 + $time);
            $nickname = $deviceItem['device_nickname'];

            // 如果10分钟前 已经推送过该信息
            $isPushed = (new PushLogAction())->log($uid, $did, $eventType);
            if ($isPushed) {
                $output->info('did=' . $did . ' last 10 min had pushed uid=' . $uid);
                continue;
            }
            // 推送消息
            $data = [
                'to_uid' => $uid,
                'title' => lang('device_notify_title', ['nickname' => $nickname, 'device_type' => lang('water_pump', '', $lang)], $lang),
                'content' => lang('device_notify_content', ['nickname' => $nickname, 'time' => $localTime, 'content' => $content], $lang)
            ];
            CommandHelper::pushUMeng($data);
        }
    }

    private function offline(Output $output,$size=10){
        $time = microtime(true);
        $output->info('offline start');
        $result = CommandHelper::offline_notify($size,new WaterPumpDeviceLogic(),'water_pump');
        $cost_time = microtime(true) - $time;
        if($result['status']){
            $cnt = count($result['info']);
            $output->info('effect '.$cnt);
        }
        $output->info('cost '.$cost_time.' s');
        $output->info('offline end');
    }

    private function clear(Output $output){
        $output->highlight('water_pump clear start');
        //1. tcp接口日志3天内保留
        $now = time();
        $dataTimestamp = $now - 3*3600;
        (new WaterPumpTcpLogAction())->clearExpiredData($dataTimestamp);

        //2. 事件日志31天内保留
        $dataTimestamp = $now - 10*3600;
        (new WaterPumpDeviceEventAction())->clearExpiredData($dataTimestamp);

        //3. 删除7天sunsun_log表的日志
        $dataTimestamp = $now - 7*24*3600;
        (new TcpLogAction())->clearExpiredData($dataTimestamp);
        $output->highlight('water_pump clear end');
    }


}